package com.chagee.store.operation.server.facade.provider;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chagee.base.exception.SoaException;
import com.chagee.base.utils.*;
import com.chagee.store.operation.api.request.*;
import com.chagee.store.operation.api.response.*;
import com.chagee.store.operation.api.service.ISupplierWorkOrderApi;
import com.chagee.store.operation.server.entity.WorkOrderDO;
import com.chagee.store.operation.server.model.lock.PushFinanceLock;
import com.chagee.store.operation.server.model.lock.SettlementOfflinePayLock;
import com.chagee.store.operation.server.model.param.WorkOrderDetailRequest;
import com.chagee.store.operation.server.redis.service.RedisLockService;
import com.chagee.store.operation.server.service.biz.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author : hk
 * @Date : 2024/9/26
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class SupplierWorkOrderApiImpl implements ISupplierWorkOrderApi {

	@Resource
	private WorkOrderBizService workOrderBizService;

	@Resource
	private WorkOrderDeviceBizService workOrderDeviceBizService;

	@Resource
	private TaskExecutionBizService taskExecutionBizService;

	@Resource
	private StoreSettlementBizService storeSettlementBizService;

	@Resource
	private SupplierWorkOrderBizService supplierWorkOrderBizService;

	@Resource
	private SupplierDetailBizService supplierDetailBizService;

	@Resource
	private RedisLockService redisLockService;

	private static final int EXPORT_PAGE_SIZE = 200;

	@Override
	public SoaResponse<PaginationData<WorkOrderResponse>, Void> list(@Valid PaginationRequest<WorkOrderRequest> request) {
		PaginationData<WorkOrderResponse> result = workOrderBizService.query(request);
		return SoaUtil.ok(result);
	}

	@Override
	public SoaResponse<WorkOrderResponse, Void> queryDetail(WorkOrderInfoRequest request) {
		WorkOrderDetailRequest detailRequest = new WorkOrderDetailRequest();
		detailRequest.setWorkOrderNumber(request.getWorkOrderNumber());
		WorkOrderResponse result = workOrderBizService.queryDetail(detailRequest);
		return SoaUtil.ok(result);
	}

	@Override
	public SoaResponse<StoreWorkOrderDeviceResponse, Void> getWorkOrderDevice(String workOrderNumber) {
		StoreWorkOrderDeviceResponse deviceList = workOrderDeviceBizService.getDeviceList(workOrderNumber);
		return SoaUtil.ok(deviceList);
	}

	@Override
	public SoaResponse<PaginationData<TaskExecutionResponse>, Void> queryTaskList(PaginationRequest<TaskExecutionRequest> request) {
		PaginationData<TaskExecutionResponse> data = taskExecutionBizService.query(request);
		return SoaUtil.ok(data);
	}


	@Override
	public SoaResponse<List<WorkOrderResponse>, Void> export(WorkOrderRequest request) {

		List<SearchSupplierResponse> supplierList = supplierDetailBizService.supplierList();
		Map<String, String> supplierMap = supplierList.stream().filter(s -> StringUtils.isNotBlank(s.getCode())).collect(Collectors.toMap(SearchSupplierResponse::getCode, SearchSupplierResponse::getName, (a, b) -> b));

		List<WorkOrderResponse> responses = new ArrayList<>();
		Page<WorkOrderDO> page = new Page<>();
		page.setSize(EXPORT_PAGE_SIZE);
		int pageNum = 1;
		int currentSize = EXPORT_PAGE_SIZE;
		Page<WorkOrderDO> workOrderDOPage;
		List<WorkOrderResponse> workOrderResponses;
		while (currentSize >= EXPORT_PAGE_SIZE) {
			page.setCurrent(pageNum++);
			workOrderDOPage = workOrderBizService.queryWorkOrderPage(page, request);
			currentSize = workOrderDOPage.getRecords().size();
			if (CollectionUtils.isEmpty(workOrderDOPage.getRecords())) {
				break;
			}
			workOrderResponses = workOrderBizService.queryWorkOrderByPage(workOrderDOPage.getRecords(), supplierMap);
			responses.addAll(workOrderResponses);
		}
		return SoaUtil.ok(responses);
	}

	@Override
	public SoaResponse<PaginationData<SettlementResponse>, Void> querySettlementPage(PaginationRequest<SettlementRequest> request) {
		PaginationData<SettlementResponse> settlementPage = storeSettlementBizService.querySettlementPage(request);
		return SoaUtil.ok(settlementPage);
	}

	@Override
	public SoaResponse<Boolean, SoaException> supplierVerify(SupplierVerifyRequest request) {
		Boolean result = storeSettlementBizService.supplierVerify(request);
		return SoaUtil.ok(result);
	}

	/**
	 * 结算单详情
	 */
	public SoaResponse<SettlementResponse, Void> settlementDetail(SettlementDetailRequest request) {
		SettlementResponse response = storeSettlementBizService.settlementDetail(request);
		return SoaUtil.ok(response);
	}

	public SoaResponse<PaginationData<WorkOrderResponse>, Void> queryOrderList(PaginationRequest<SettlementOrderRequest> request) {
		PaginationData<WorkOrderResponse> data = storeSettlementBizService.queryOrderList(request);
		return SoaUtil.ok(data);
	}

	public SoaResponse<String, SoaException> getUploadInvoiceUrl(InvoiceRequest request) {

		return SoaUtil.ok(storeSettlementBizService.getUploadInvoiceUrl(request));
	}

	public SoaResponse<Boolean, SoaException> orderAppeal(OrderAppealRequest request) {
		Boolean result = supplierWorkOrderBizService.orderAppeal(request);
		return SoaUtil.ok(result);
	}

	@Override
	public SoaResponse<Boolean, SoaException> supplierRejected(@Valid SupplierRejectedRequest request) {
		Boolean result = storeSettlementBizService.supplierRejected(request);
		return SoaUtil.ok(result);
	}

	@Override
	public SoaResponse<Boolean, SoaException> offlinePay(@Valid OfflinePayRequest request) {

		SettlementOfflinePayLock lock = null;
		if (StringUtils.isNotBlank(request.getSettlementNo())) {
			lock = new SettlementOfflinePayLock(request.getSettlementNo());
		}
		try {
			redisLockService.lockElseThrowError(lock, "请稍后再试");
			Boolean result = storeSettlementBizService.offlinePay(request);
			return SoaUtil.ok(result);
		} finally {
			redisLockService.unLock(lock);
		}
	}

}
